# -*- coding: utf-8 -*-
"""
@Time    : 2024/8/8 13:36 
@Author  : ZhangShenao 
@File    : 1.使用全局钩子.py
@Desc    : 使用Flask的全局钩子

Flask的全局钩子是通过装饰器的形式实现的,主要包含如下四种:
1. before_request: 在每次请求执行前调用
2. after_request: 在每次请求执行结束后调用
3. teardown_request: 在每次请求上下文被销毁时调用,如果有异常抛出,可以捕获到异常信息

全局钩子是一种AOP的编程方式,可以在请求执行的前后织入一些通用的增强逻辑
如身份认证、鉴权、限流、日志等等

"""
from flask import Flask, Response, request, abort

app = Flask(__name__)
app.config['DEBUG'] = False


@app.before_request
def before_request():
    """
    before_request钩子函数,在每次请求执行前调用
    可以进行一些通用的前置校验,如鉴权、限流等
    """
    print("before_request 钩子执行")

    # 校验用户的token信息
    token = request.headers.get("X-TOKEN")
    if token is None or token != "123456":
        abort(403)


@app.after_request
def after_request(response: Response) -> Response:
    """
    after_request钩子函数,在每次请求执行结束后调用
    可以对响应进行一些增强,如日志记录、响应数据加密、增加通用的Header等
    after_request钩子需要接收一个Response对象,并在函数中返回

    """
    # after_request钩子需要接收response响应对象
    print(f"after_request 钩子执行, 响应数据类型: {type(response)}, 响应数据: {response}")

    # 对Response进行增强
    response.headers["UID"] = "123"

    # 需要把Response对象返回
    return response


@app.teardown_request
def teardown_request(exception):
    """
    teardown_request钩子函数,在每次请求上下文被销毁时调用
    如果有异常抛出,可以捕获到异常信息
    """
    print(f"teardown_request 钩子执行")

    if exception is not None:
        print(f"捕获到异常信息: {exception}")


@app.route("/hello", methods=["GET"])
def hello() -> str:
    print("路由函数执行")
    # print(1 / 0)  # 模拟异常
    return "Welcome to Flask!"


if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)
